
/**
 * Project Name:cats-core-impl
 * File Name:UserServiceImpl.java
 * Package Name:com.catsic.core.user.service
 * Date:2014年2月27日上午11:26:52
 * Copyright (c) 2014, oa.catsic.com All Rights Reserved.
 */
 
package com.catsic.core.user.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.catsic.base.BaseServiceImpl;
import com.catsic.base.exception.CatsicException;
import com.catsic.core.UserInfo;
import com.catsic.core.conditon.UserCondition;
import com.catsic.core.constants.Constants;
import com.catsic.core.convert.Converts;
import com.catsic.core.depart.service.DepartService;
import com.catsic.core.entity.Depart;
import com.catsic.core.entity.Organ;
import com.catsic.core.entity.Role;
import com.catsic.core.entity.User;
import com.catsic.core.exception.CatsicExceptionCode;
import com.catsic.core.form.RoleForm;
import com.catsic.core.form.UserForm;
import com.catsic.core.organ.service.OrganService;
import com.catsic.core.resource.service.ResourceService;
import com.catsic.core.role.service.RoleService;
import com.catsic.core.specification.UserSpec;
import com.catsic.core.status.UserStatus;
import com.catsic.core.user.dao.UserDao;
import com.catsic.core.user.service.UserService;
import com.catsic.pub.drawer.service.DrawerService;
import com.catsic.pub.entity.Drawer;

/**
 * ClassName: UserServiceImpl
 * Description: 用户Service实现类
 * date: 2014年2月27日 上午11:26:52
 * author: yangyd
 */
@Service("userService")
public class UserServiceImpl extends BaseServiceImpl<User, String> implements UserService{
	
	/**
	 * passwordEncoder:密码编译
	 */
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	/**
	 * userDao:用户Dao
	 */
	@Autowired
	private UserDao userDao;
	
	/**
	 * OrganService:机构Service
	 */
	@Autowired
	private OrganService organService;
	
	/**
	 * DepartService:部门Service
	 */
	@Autowired
	private DepartService departService;
	
	/**
	 * roleService:角色Service
	 */
	@Autowired
	private RoleService roleService;
	
	@Autowired
	private DrawerService drawerService;
	
	/**
	 * ResourceService:资源Service
	 */
	@Autowired
	private ResourceService resourceService;
	
	/**
	 * @see com.catsic.core.base.BaseServiceImpl#add(java.lang.Object)
	 */
	@Override
	public UserForm add(UserForm form) {
		checkUserName(form.getUsername());
		if(!this.checkPassword(form.getPassword())){
			throw new CatsicException(CatsicExceptionCode.用户管理_密码长度必须在8_16位,8,16);
		}
		Organ organ = organService.findById(form.getOrganId());
		User user = new User();
		if(StringUtils.isNotBlank(form.getDepartId())){
			Depart depart = departService.findById(form.getDepartId());
			user.setDepart(depart);
		}
		
		
		user.setUsername(form.getUsername());
		user.setPassword(passwordEncoder.encode(form.getPassword()));
		user.setRealname(form.getRealname());
		user.setIdentity(form.getIdentity());
		user.setMobile(form.getMobile());
		user.setEmail(form.getEmail());
		user.setPwdLastUpdate(new Date());
		user.setOrgan(organ);
		return Converts.convert(super.add(user));
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#update(com.catsic.core.entity.User)
	 */
	@Override
	public UserForm update(UserForm form) {
		User user = findById(form.getId());
		if(StringUtils.isBlank(form.getDepartId())){
			user.setDepart(null);
		}else{
			Depart depart = departService.findById(form.getDepartId());
			user.setDepart(depart);
		}
		user.setRealname(form.getRealname());
		user.setIdentity(form.getIdentity());
		user.setMobile(form.getMobile());
		user.setEmail(form.getEmail());
		return Converts.convert(super.add(user));
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#freeze(java.lang.Long)
	 */
	@Override
	public void freeze(String id) {
		User user = findById(id);
		user.setStatus(UserStatus.冻结);
		super.add(user);
	}

	/**
	 * @see com.catsic.core.user.service.UserService#cancel(java.lang.Long)
	 */
	@Override
	public void cancel(String id) {
		User user = findById(id);
		user.setStatus(UserStatus.注销);
		super.add(user);
	}

	/**
	 * @see com.catsic.core.user.service.UserService#activite(java.lang.Long)
	 */
	@Override
	public void activite(String id) {
		User user = findById(id);
		user.setStatus(UserStatus.激活);
		super.add(user);
	}

	/**
	 * @see com.catsic.core.user.service.UserService#bind(java.lang.String, java.lang.String[])
	 */
	@Override
	public void bind(String id,String roleIds[]) {
		User user = findById(id);
		List<Role> listRole = new ArrayList<Role>();
		for(String roleId : roleIds){
			Role role = roleService.findById(roleId);
			listRole.add(role);
		}
		user.setRoles(listRole);
		super.add(user);
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#findById(java.lang.Long)
	 */
	@Override
	public User findById(String id){
		User user = getById(id);
		if(null == user){
			throw new CatsicException(CatsicExceptionCode.实体不存在, Constants.USER);
		}
		return user;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#findUserById(java.lang.Long)
	 */
	@Override
	public UserForm findUserById(String id){
		User user = findById(id);
		return Converts.convert(user);
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#findRoleById(java.lang.String)
	 */
	public List<RoleForm> findRoleById(String id){
		User user = findById(id);
		List<Role> list = user.getRoles();
		List<RoleForm> listForm = new ArrayList<RoleForm>();
		for(Role role : list){
			listForm.add(Converts.convert(role));
		}
		return listForm;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#checkUserName(java.lang.String)
	 */
	@Override
	public void checkUserName(String username) {
		if(hasSameUserName(username)){
			throw new CatsicException(CatsicExceptionCode.用户管理_登录昵称重复);
		}
	}
	
    /**
	 * @see com.catsic.core.user.service.UserService#initPassword(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public void initPassword(String id,String newPassword) {
		User user = findById(id);
		user.setPassword(passwordEncoder.encode(newPassword));
		user.setPwdLastUpdate(new Date());
		super.update(user);
	}
	
    /**
	 * @see com.catsic.core.user.service.UserService#initAllPassword(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public void initAllPassword(String organCode,String newPassword) {
		List<User> list = findByLikeOrganCode(organCode + "%");
		for(User user : list){
			user.setPassword(passwordEncoder.encode(newPassword));
			user.setPwdLastUpdate(new Date());
			super.update(user);
		}
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#hasSameUserName(java.lang.String)
	 */
	@Override
	public boolean hasSameUserName(String username) {
		return userDao.findByUsername(username) != null;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#checkPassword(java.lang.String)
	 */
	@Override
	public boolean checkPassword(String password) {
		if(StringUtils.length(password)<8 || StringUtils.length(password)>16){
			return false;
		}
		return true;
	}
	
    /**
	 * @see com.catsic.core.user.service.UserService#changePassword(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public void changePassword(String username, String oldPassword, String newPassword) {
		
		if(!this.checkPassword(newPassword)){
			throw new CatsicException(CatsicExceptionCode.用户管理_密码长度必须在8_16位,8,16);
		}
		
		User user = userDao.findByUsername(username);
		
		if(!passwordEncoder.matches(oldPassword,user.getPassword())){
			throw new CatsicException(CatsicExceptionCode.用户管理_原密码错误);
		}

		user.setPassword(passwordEncoder.encode(newPassword));
		user.setPwdLastUpdate(new Date());
		super.update(user);
	}

	/**
	 * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
	 */
	@Override
	public UserDetails loadUserByUsername(String username){
		User user = userDao.findByUsername(username);
		if(null == user){
			throw new CatsicException(CatsicExceptionCode.实体不存在,Constants.USER);
		}
		
		if(UserStatus.冻结 == user.getStatus()){
			throw new CatsicException(CatsicExceptionCode.用户管理_用户当前状态为冻结_不可操作, Constants.FREEZE);
		}
		
		if(CollectionUtils.isEmpty(user.getAuthorities())){
			throw new CatsicException(CatsicExceptionCode.用户管理_权限不能为空, Constants.AUTHPRITY);
		}
		
		validateUserUnLock(username);
		
		UserInfo userInfo = new UserInfo(user.getUsername(),user.getPassword(),user.getAuthorities());
		
		userInfo.setUserId(user.getId());
		userInfo.setOrganId(user.getOrgan().getId());
		userInfo.setOrganName(user.getOrgan().getName());
		userInfo.setOrganCode(user.getOrgan().getCode());
		if(user.getDepart() != null){
			userInfo.setDepartId(user.getDepart().getId());
			userInfo.setDepartName(user.getDepart().getName());
		}
		
		userInfo.setPwdIsValid(checkPwd(user));
		
		//userInfo.getResources().addAll(resourceService.findByUserIdOrderByCodeAsc(user.getId()));
		
		Organ organ = user.getOrgan();
		while(StringUtils.length(organ.getCode())!=3){
			if(StringUtils.length(organ.getCode()) == 9){
				userInfo.setCorganId(organ.getId());
				userInfo.setCorganCode(organ.getCode());
				userInfo.setCorganName(organ.getName());
			}else if(StringUtils.length(organ.getCode()) == 6){
				userInfo.setPorganId(organ.getId());
				userInfo.setPorganCode(organ.getCode());
				userInfo.setPorganName(organ.getName());
			}
			organ = organ.getParent();
		}
		return userInfo;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#findAll(com.catsic.core.conditon.UserCondition, org.springframework.data.domain.Pageable)
	 */
	public Page<UserForm> findAll(UserCondition condition, Pageable pageable){
		UserSpec spec = new UserSpec(condition);
		Page<User> page = userDao.findAll(spec, pageable);
		List<UserForm> listForm = new ArrayList<UserForm>();
		for(User user :page.getContent()){
			listForm.add(Converts.convert(user));
	    }
	    Page<UserForm> page_ = new PageImpl<UserForm>(listForm,pageable,page.getTotalElements());
	    return page_;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#validatePassword(java.lang.String, java.lang.String, java.lang.String)
	 */
	public boolean validatePassword(String username,String password,String saltsPassword){
		return passwordEncoder.matches(password, saltsPassword);
	}
	
	public User findByUsername(String username){
		return userDao.findByUsername(username);
	}
	
	public User findByIdentity(String identity){
		return userDao.findByIdentity(identity);
	}
	
	@Override
	public void validateUserUnLock(String username){
		User user = findByUsername(username);
		
		/**
		 * 首次登陆
		 */
		if(user.getFailureCount() == null || user.getLastLogin() == null){
			return;
		}
		
		Drawer drawer = drawerService.findByCode(Constants.密码错误次数);
		
		if(drawer == null || Integer.valueOf(drawer.getValue()) < 0){
			throw new CatsicException(CatsicExceptionCode.用户管理_密码错误次数_参数设置错误);
		}
		
		/**
		 * 失败次数小于5次，
		 */
		if(user.getFailureCount() < Integer.valueOf(drawer.getValue())){
			return;
		}
		
		Integer lockTime = Integer.valueOf(drawerService.findByCode(Constants.账户锁定时间).getValue());
		/**
		 * 账户被锁定后，30分钟后才可以登录
		 */
		if(user.getLastLogin() != null && new DateTime().plusMinutes(-lockTime).isBefore(user.getLastLogin())){
			throw new CatsicException(CatsicExceptionCode.用户管理_用户已被锁定, lockTime);
		}
	}
	
	@Override
	public void resetFailureCount(String username) {
		User user = findByUsername(username);
		user.setFailureCount(0); 
		user.setLastLogin(new Date());
		update(user);
	}

	@Override
	public Integer[] updateFailureCount(String username) {
		Drawer drawer = drawerService.findByCode(Constants.密码错误次数);
		Integer count = 0;
		try {
			count = Integer.valueOf(drawer.getValue());
			if(count < 0){
				throw new CatsicException(CatsicExceptionCode.用户管理_密码错误次数_参数设置错误);
			}
		} catch (Exception e) {
			throw new CatsicException(CatsicExceptionCode.用户管理_密码错误次数_参数设置错误);
		}
		User user = findByUsername(username);
		int failureCount = 0;
		if(count > 0){
			failureCount = (user.getFailureCount() == null ? 0 : user.getFailureCount()) + 1;
		}
		user.setFailureCount(failureCount);
		user.setLastLogin(new Date());
		update(user);
		Integer params[] = {failureCount,Integer.valueOf(drawer.getValue())};
		return params;
	}
	
	/**
	 * 校验密码是否有效,true:有效，false:无效
	 * @param user
	 * @return
	 */
	private boolean checkPwd(User user){
		DateTime date = user.getPwdLastUpdate();
		Drawer drawer = drawerService.findByCode(Constants.是否修改初始密码);
		if(Constants.密码开关设置.equals(drawer.getValue())){
			if(date == null){
				return false;
			}
		}
		
		if(date == null){
			date = user.getCreateTime();
		}
		
		if(date == null){
			return false;
		}
		
		return checkRegularPwd(date);
	}
	

	private boolean checkRegularPwd(DateTime date){
		Drawer drawer = drawerService.findByCode(Constants.是否定期修改密码);
		if(drawer.getValue().equals(Constants.密码开关设置)){
			
			drawer = drawerService.findByCode(Constants.定期修改密码天数);
			try {
				Integer days = Integer.valueOf(drawer.getValue());

				if(drawer == null || days < 0){
					throw new CatsicException(CatsicExceptionCode.用户管理_定期修改密码天数_参数设置错误);
				}
				
				if(DateTime.parse(date.toString("yyyy-MM-dd")).plusDays(days).isBeforeNow()){
					return false;
				}
			} catch (Exception e) {
				throw new CatsicException(CatsicExceptionCode.用户管理_定期修改密码天数_参数设置错误);
			}
		}
		return true;
	}
	
	/**
	 * @see com.catsic.core.user.service.UserService#findByLikeOrganCode(java.lang.String)
	 */
	public List<User> findByLikeOrganCode(String organCode){
		return userDao.findByLikeOrganCode(organCode);
	}
}
